home *** CD-ROM | disk | FTP | other *** search
/ PC Media 4 / PC MEDIA CD04.iso / share / prog / pcl4c42 / term.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-15  |  12.5 KB  |  458 lines

  1. /*
  2. **                    --- term.c ---
  3. **
  4. **  EXAMPLE CODE: Terminal emulator. Can transfer files using
  5. **  ASCII, XMODEM, YMODEM, and YMODEM-G protocols.
  6. **
  7. **  See TERM.CFG for configuration parameters.
  8. **
  9. **  Link with ALLOCSEG, TERM_IO, MODEM_IO, DIR_IO, CRC, DOS, AMODEM,
  10. **  XYMODEM, XYPACKET, SI, and OPCODES. Files SI.C and OPCODES.C used
  11. **  for scripts only. See TERM makefiles and TERM.CFG.
  12. **
  13. **  Do NOT select YMODEM-G when using a null modem cable unless you are
  14. **  certain that RTS & CTS are reversed ( this is usually not true ).
  15. **
  16. **  This example program (not the PCL4C library) is donated to
  17. **  the Public Domain by MarshallSoft Computing, Inc. It is
  18. **  provided as an example of the use of the PCL4C.
  19. **
  20. */
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <ctype.h>
  25. #include <fcntl.h>
  26. #include <string.h>
  27. #include <sys\types.h>
  28. #include <sys\stat.h>
  29. #include <malloc.h>
  30. #include <dos.h>
  31. #include "term.cfg"
  32. #include "pcl4c.h"
  33. #include "ascii.h"
  34. #include "term.h"
  35. #include "dir_io.h"
  36. #include "term_io.h"
  37. #include "dos_io.h"
  38. #include "modem_io.h"
  39. #include "crc.h"
  40. #include "xymodem.h"
  41. #include "amodem.h"
  42. #include "term.h"
  43. #include "allocseg.h"
  44. #include "timing.h"
  45. #if SCRIPTS
  46. #include "si.h"
  47. #endif
  48.  
  49. #define FALSE 0
  50. #define TRUE !FALSE
  51. #define NORMAL 0x07
  52. #define INVERSE 0x70
  53. #define MESSAGE_POS 48
  54.  
  55. /* local prototypes */
  56. void MyStart(int Port,int BaudCode);
  57. void ProcessESC(void);
  58. void ShowMessage(int Pos,char *Msg);
  59. void ShowMenuMessage(void);
  60.  
  61. /*** Global variables ***/
  62.  
  63. #define SIO_BUF_SIZE 2048
  64.  
  65. int Port;               /* current COM port [0..3] */
  66. char FileSpec[15];      /* file name specification */
  67. char Filename[15];      /* file name buffer */
  68. char Buffer[1024];      /* block buffer */
  69. char *BaudRate[10] =  {"300","600","1200","2400","4800","9600",
  70.                        "19200","38400","57600","115200"};
  71. int BaudCode;           /* baud rate code ( index into BaudRate[] ) */
  72. char *ModelText[4] = {"Small","Compact","Medium","Large"};
  73. char NCGchar   = NAK;
  74. int  OneKflag  = FALSE;
  75. int  BatchFlag = FALSE;
  76. char Protocol  = 'X';
  77. char TermChar  = 0x00;
  78. int  CharPace  = 0;
  79. int  Timeout   = 10;
  80. int  EchoFlag  = TRUE;
  81.  
  82. /*** main program ***/
  83.  
  84. void main(int argc,char *argv[])
  85. {int DataFlag = FALSE;
  86.  char c;
  87.  int i, k;
  88.  int n, rc;
  89.  int Delta;         /* delta port status */
  90.  int Status;        /* port status */
  91.  int Version;
  92.  char temp[81];
  93.  /* right number of parameters ? */
  94.  if((argc<3)||(argc>4))
  95.      {printf("Usage: 'TERM port baud' -- example 'TERM 1 9600 {script}'\n");
  96.       exit(1);
  97.      }
  98.  /* get port number from command line */
  99.  Port = atoi(argv[1]) - 1;
  100.  if((Port<0) || (Port>15))
  101.      {printf("Port must be 1 to 16\n");
  102.       exit(1);
  103.      }
  104.  /* get baud rate from command line */
  105.  BaudCode = BaudMatch(argv[2]);
  106.  if(BaudCode<0)
  107.      {printf("Cannot recognize baud rate = %s\n",argv[2]);
  108.       exit(1);
  109.      }
  110.  
  111. #if 0
  112.  /*** Custom Configuration: 4 port card ***/
  113.  SioIRQ(COM1,IRQ4);
  114.  SioIRQ(COM2,IRQ3);
  115.  /* use IRQ2 for COM3 & COM4 */
  116.  SioIRQ(COM3,IRQ2);
  117.  SioIRQ(COM4,IRQ2);
  118. #endif
  119.  
  120. #if 0
  121.  /*** Custom Configuration: DigiBoard PC/8 ***/
  122.  puts("Configuring DigiBoard as COM1-COM8 (IRQ5)");
  123.  SioDelay(18);
  124.  /* use 0x140 for odd IRQs & 0x141 for even IRQs */
  125.  SioPorts(8,COM1,0x140,DIGIBOARD);
  126.  /* set DigiBoard UART addresses */
  127.  ErrorCheck( SioUART(Port,0x100+8*Port) );
  128.  /* set DigiBoard for IRQ5 */
  129.  ErrorCheck( SioIRQ(Port,IRQ5) );
  130. #endif
  131.  
  132. #if 0
  133.  /*** Custom Configuration: BOCA 16 port dumbcard ***/
  134.  puts("Configuring BOCA Board as COM1-COM16 (IRQ5)");
  135.  SioDelay(18);
  136.  /* use base port + 7 */
  137.  SioPorts(16,COM1,0x100+7,BOCABOARD);
  138.  /* set BOCA Board UART addresses */
  139.  ErrorCheck( SioUART(Port,0x100+8*Port) );
  140.  /* set BOCA Board for IRQ5 */
  141.  ErrorCheck( SioIRQ(Port,IRQ5) );
  142. #endif
  143.  
  144.  /********************************************************/
  145.  
  146.  /* setup receive buffer */
  147.  ErrorCheck( SioRxBuf(Port,AllocSeg(2048),Size2K) );
  148.  if(SioInfo('I'))
  149.    {/* setup transmit buffer */
  150.     ErrorCheck( SioTxBuf(Port,AllocSeg(2048),Size2K) );
  151.    }
  152.  /* set parms & reset (initialize) COM port */
  153.  SioParms(Port,NoParity,OneStopBit,WordLength8);
  154.  MyStart(Port,BaudCode);
  155.  /* set DTR and RTS */
  156.  SioDTR(Port,'S');
  157.  SioRTS(Port,'S');
  158.  /* init CRC table */
  159.  InitCRC();
  160.  /* initialize screen */
  161.  Scroll(0,0,24,79,0,NORMAL);
  162.  /* display status message */
  163.  ShowMenuMessage();
  164.  Position(1,0);
  165.  /* display some info */
  166.  printf("  -- TERM: 8/21/94 --\n\n");
  167.  Version = SioInfo('V');
  168.  printf("      Library: %d.%d\n",Version>>4,0x0f&Version);
  169.  printf(" Memory Model: %s\n",ModelText[3&SioInfo('M')] );
  170.  printf("TX Interrupts: ");
  171.  if(SioInfo('I')) puts("YES");
  172.  else puts("NO");
  173.  printf("   Parameters: 8N1\n");
  174. #if RTS_CTS_CONTROL
  175.  SioFlow(Port,10*ONE_SECOND);
  176.  printf(" Flow Control: YES\n");
  177. #else
  178.  printf(" Flow Control: NO\n");
  179. #endif
  180.  
  181. #if 0
  182.  /* Set FIFO level */
  183.  printf("   16550 UART: ");
  184.  if( SioFIFO(Port,LEVEL_14) ) printf("YES\n");
  185.  else printf("NO\n");
  186. #endif
  187.  
  188.  /* clear PCL4C receive buffer */
  189.  ErrorCheck( SioRxFlush(Port) );
  190.  printf("\n");
  191.  
  192.  /* see TERM.H for definition of AT_COMMAND_SET */
  193. #if AT_COMMAND_SET
  194.  /* wait for Modem to say its ready */
  195.  printf("  <<Waiting for Modem DSR>>\n");
  196.  while( !SioDSR(Port) )
  197.      {if(SioKeyPress()||SioBrkKey()) MyExit(0,"Aborted by user");
  198.       putchar('.');
  199.       SioDelay(18);
  200.      }
  201.  printf("  <<DSR on>>\n");
  202. #endif
  203.  
  204. #if RTS_CTS_CONTROL
  205.  printf("  <<Waiting for Modem CTS>>\n");
  206.  while( !SioCTS(Port) )
  207.      {if(SioKeyPress()||SioBrkKey()) MyExit(0,"Aborted by user");
  208.       putchar('.');
  209.       SioDelay(18);
  210.      }
  211.  printf("  <<CTS on>>\n");
  212. #endif
  213.  
  214. #if AT_COMMAND_SET
  215.  /* initialize (Hayes compatible) modem */
  216.  ModemSendTo(Port,4,"AT!");
  217.  ModemEcho(Port,10);
  218.  ModemSendTo(Port,4,"AT E1 S7=60 S11=60 V1 X1 Q0 S0=1!");
  219.  if(ModemWaitFor(Port,5*ONE_SECOND,TRUE,"OK"))
  220.    {/* modem is ready */
  221.     puts("\n  <<MODEM READY>>");
  222.    }
  223.  else printf("\n  <<WARNING: Expected OK not received>>\n");
  224. #endif
  225.  
  226. #if SCRIPTS
  227.  if(argc==4)
  228.    {/* call script interpreter */
  229.     i = si(Port,argv[3],FALSE);
  230.     if(i<0) SaySiErr(i);
  231.    }
  232. #endif
  233.  
  234.  /* enter terminal loop */
  235.  SioRxFlush(Port);
  236.  puts("  <<Entering terminal loop>>");
  237.  while(1)
  238.      {/* Control-BREAK ? */
  239.       if(SioBrkKey()) MyExit(0,"User pressed Ctrl-BREAK");
  240.       /* was key pressed ? */
  241.       if(SioKeyPress())
  242.           {/* read key press */
  243.            i = SioKeyRead();
  244.  
  245. if((char)i=='#') printf("RX count = %d\n", SioInfo('R') );
  246.  
  247.            if((char)i==ESC)
  248.                {/* process user's request */
  249.                 ProcessESC();
  250.                 ShowMenuMessage();
  251.                 continue;
  252.                }
  253.            else SioPutc(Port,(char)i);
  254.           }
  255.       /* was break detected ? */
  256.       if( SioBrkSig(Port,'D') ) DisplayLine("BREAK detected ",NULL,0);
  257.       /* any incoming over serial port ? */
  258.       i = SioGetc(Port,1);
  259.       if(i>-1)
  260.           {/* good character */
  261.            if(DataFlag&((i<0x20)||(i>0x7e)))
  262.                {MyCrtWrite('^');
  263.                 MyCrtWrite((char)('@'+i));
  264.                }
  265.            else MyCrtWrite((char)i);
  266.           }
  267.      } /* end -- key pressed */
  268. }
  269.  
  270. /*** write to screen except for bottom line ***/
  271.  
  272. void MyCrtWrite(char ch)
  273. {/* write character */
  274.  SioCrtWrite(ch);
  275.  /* scroll all but bottom line */
  276.  if(GetRow()==24)
  277.     {Scroll(0,0,23,79,1,NORMAL);
  278.      Position(23,0);
  279.     }
  280. }
  281.  
  282. /*** make multiple attempts to reset port ***/
  283.  
  284. void MyStart(int Port,int BaudCode)
  285. {int i, rc;
  286.  /* try up to 3 times to reset COM port */
  287.  for(i=0;i<3;i++)
  288.      {printf("Resetting COM%d at %s baud\n",Port+1,BaudRate[BaudCode]);
  289.       if( (rc = SioReset(Port,BaudCode))==0) return;
  290.       if(rc<0) MyExit(rc,"Error resetting port");
  291.       SioDone(Port);
  292.       /* display errors */
  293.       if(rc&OverrunError) puts("Overrun Error");
  294.       if(rc&ParityError)  puts("Parity Error");
  295.       if(rc&FramingError) puts("Framing Error");
  296.       if(rc&BreakDetect)  puts("Break Detect");
  297.      }
  298.  exit(1);
  299. }
  300.  
  301. /*** find baud rate string in table ***/
  302.  
  303. int BaudMatch(char *ptr)
  304. {int i;
  305.  /* find baud rate in table */
  306.  for(i=0;i<10;i++) if(strcmp(BaudRate[i],ptr)==0) return(i);
  307.  return(-1);
  308. }
  309.  
  310. /*** user pressed Escape */
  311.  
  312. void ProcessESC(void)
  313. {int i;
  314.  int rc;
  315.  int c1, c2;
  316.  char Answer[2]; /* array for 1 char answer */
  317.  int row, col;
  318.  /* user pressed <ESC> */
  319.  Answer[0] = '?';
  320.  Answer[1] = '\0';
  321.  DisplayLine("Q)uit P)rotocol S)end R)eceive: ",Answer,1);
  322.  if(strlen(Answer)) switch(toupper(Answer[0]))
  323.      {
  324.       case 'P':
  325. #if RTS_CTS_CONTROL
  326.           DisplayLine("A)scii X)modem Y)modem ymodem-G): ",Answer,1);
  327. #else
  328.           DisplayLine("A)scii X)modem Y)modem: ",Answer,1);
  329. #endif
  330.           if(strlen(Answer)) switch( toupper(Answer[0]) )
  331.                {
  332.                 case 'A':
  333.                     Protocol = 'A';
  334.                     ShowMenuMessage();
  335.                     TermChar = 0x18;  /* CAN or control-X */
  336.                     CharPace = 0;     /* no inter-byte delay */
  337.                     Timeout = 7;      /* timeout after 7 seconds */
  338.                     EchoFlag = TRUE;  /* do local echo */
  339.                     DisplayLine("Protocol = ASCII",NULL,1);
  340.                     break;
  341.                 case 'X':
  342.                     Protocol = 'X';
  343.                     ShowMenuMessage();
  344.                     OneKflag = FALSE;
  345.                     BatchFlag = FALSE;
  346.                     NCGchar = NAK;
  347.                     DisplayLine("Protocol = XMODEM",NULL,1);
  348.                     break;
  349.                 case 'Y':
  350.                     Protocol = 'Y';
  351.                     ShowMenuMessage();
  352.                     OneKflag = TRUE;
  353.                     BatchFlag = TRUE;
  354.                     NCGchar = 'C';
  355.                     DisplayLine("Protocol = YMODEM",NULL,1);
  356.                     break;
  357. #if RTS_CTS_CONTROL
  358.                 case 'G':
  359.                     Protocol = 'G';
  360.                     ShowMenuMessage();
  361.                     OneKflag = TRUE;
  362.                     BatchFlag = TRUE;
  363.                     NCGchar = 'G';
  364.                     DisplayLine("Protocol = YMODEM-G",NULL,1);
  365.                     break;
  366. #endif
  367.                 default:
  368.                     DisplayLine("Must answer X, Y, or G",NULL,1);
  369.                     break;
  370.                }
  371.           break;
  372.       case 'Q':
  373.           MyExit(0,"User pressed ESC");
  374.           break;
  375.       case 'R':
  376.           ShowMessage(strlen(BaudRate[BaudCode])+9,"'CTRL-X aborts'");
  377.           if(Protocol=='A')
  378.               {/* Ascii */
  379.                DisplayLine("Enter filename:",Filename,15);
  380.                if(strlen(Filename)==0) break;
  381.                RxAscii(Port,Filename,Buffer,1024,SIO_BUF_SIZE,FALSE,TermChar,Timeout,EchoFlag);
  382.                break;
  383.               }
  384.           /* XMODEM / YMODEM receive */
  385.           if(BatchFlag) YmodemRx(Port,Buffer,NCGchar);
  386.           else XmodemRx(Port,NULL,Buffer,NCGchar);
  387.           break;
  388.  
  389.       case 'S':
  390.           ShowMessage(strlen(BaudRate[BaudCode])+9,"'CTRL-X aborts'");
  391.           if(Protocol=='A')
  392.               {/* Ascii */
  393.                DisplayLine("Enter filename:",FileSpec,15);
  394.                if(strlen(FileSpec)==0) break;
  395.                TxAscii(Port,FileSpec,Buffer,1024,FALSE,CharPace,TermChar,EchoFlag);
  396.                break;
  397.               }
  398.           /* XMODEM / YMODEM send */
  399.           if(BatchFlag) YmodemTx(Port,NULL,Buffer,OneKflag);
  400.           else XmodemTx(Port,NULL,Buffer,OneKflag);
  401.           break;
  402.      default:
  403.           DisplayLine("Must answer Q, P, S, or R",NULL,0);
  404.           break;
  405.     } /* end switch */
  406. }
  407.  
  408. /*** show menu message ***/
  409.  
  410. void ShowMenuMessage(void)
  411. {char temp[80];
  412.  sprintf(temp," COM%d %s %c 'ESC for menu'  ",1+Port,BaudRate[BaudCode],Protocol);
  413.  ShowMessage(0,temp);
  414. }
  415.  
  416. /*** show chosen message ***/
  417.  
  418. void ShowMessage(int Pos,char *Msg)
  419. {int i;
  420.  int SaveRow;
  421.  int SaveCol;
  422.  int Col;
  423.  SaveRow = GetRow();
  424.  SaveCol = GetCol();
  425.  Col = MESSAGE_POS+Pos;
  426.  for(i=0;i<strlen(Msg);i++)
  427.    {Position(24,(unsigned char)Col++);
  428.     AttrWrite(Msg[i],INVERSE);
  429.    }
  430.  Position((unsigned char)SaveRow,(unsigned char)SaveCol);
  431. }
  432.  
  433. /*** exit program ***/
  434.  
  435. void MyExit(int code, char *msg)
  436. {int rc;
  437.  if(code<0) SioError(code);
  438.  SioDone(Port);
  439.  printf("\nTERMINATING: %s\n",msg);
  440.  exit(0);
  441. }
  442.  
  443. /*** check for error ***/
  444.  
  445. void ErrorCheck(int Code)
  446. {/* trap PCL error codes */
  447.  if(Code<0)
  448.      {SioError(Code);
  449.       SioDone(Port);
  450.       exit(1);
  451.      }
  452. } /* end ErrorCheck */
  453.  
  454. int GetBufSize(void)
  455. {int BufSize = SIO_BUF_SIZE;
  456.  return BufSize;
  457. }
  458.